using System;
using Headspring.Training.DataAccess.Impl;
using Headspring.Training.Domain.Model;
using Headspring.Training.Domain.Services;
using NHibernate;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;

namespace Headspring.Training.DataAccess.IntegrationTests
{
	[TestFixture]
	public class WorkOrderRepositoryTester : RepositoryBase
	{
		[Test]
		public void ShouldSaveWorkOrder()
		{
			TestHelper.ClearTables();

			Employee creator = new Employee("1", "1", "1", "1");
			Employee assignee = new Employee("2", "2", "2", "2");
			WorkOrder order = new WorkOrder();
			order.Creator = creator;
			order.Assignee = assignee;
			order.CreatedDate = new DateTime(1999, 1, 1);
			order.CompletedDate = new DateTime(1999, 1, 2);
			order.Title = "foo";
			order.Description = "bar";
			order.Status = WorkOrderStatus.InProgress;
			order.Number = "123";

			ISession session = getSession();
			session.SaveOrUpdate(creator);
			session.SaveOrUpdate(assignee);
			session.Flush();

			IWorkOrderRepository repository = new WorkOrderRepository();
			repository.Save(order);

			session.Dispose();

			ISession session2 = getSession();
			WorkOrder rehydratedWorkOrder = session2.Load<WorkOrder>(order.Id);
			Assert.That(rehydratedWorkOrder.Id, Is.EqualTo(order.Id));
			Assert.That(rehydratedWorkOrder.Creator.Id, Is.EqualTo(order.Creator.Id));
			Assert.That(rehydratedWorkOrder.Assignee.Id, Is.EqualTo(order.Assignee.Id));
			Assert.That(rehydratedWorkOrder.CreatedDate, Is.EqualTo(order.CreatedDate));
			Assert.That(rehydratedWorkOrder.CompletedDate, Is.EqualTo(order.CompletedDate));
			Assert.That(rehydratedWorkOrder.Title, Is.EqualTo(order.Title));
			Assert.That(rehydratedWorkOrder.Description, Is.EqualTo(order.Description));
			Assert.That(rehydratedWorkOrder.Status, Is.EqualTo(order.Status));
			Assert.That(rehydratedWorkOrder.Number, Is.EqualTo(order.Number));
		}

		[Test]
		public void ShouldGetWorkOrderByNumber()
		{
			TestHelper.ClearTables();

			Employee creator = new Employee("1", "1", "1", "1");
			WorkOrder order1 = new WorkOrder();
			order1.Creator = creator;
			order1.CreatedDate = new DateTime(1999, 1, 1);
			order1.Number = "123";
			WorkOrder order2 = new WorkOrder();
			order2.Creator = creator;
			order2.CreatedDate = new DateTime(1999, 1, 1);
			order2.Number = "456";


			ISession session = getSession();
			session.SaveOrUpdate(creator);
			session.SaveOrUpdate(order1);
			session.SaveOrUpdate(order2);
			session.Flush();
			session.Dispose();

			IWorkOrderRepository repository = new WorkOrderRepository();
			WorkOrder order123 = repository.GetWorkOrder("123");
			Assert.That(order123.Id, Is.EqualTo(order1.Id));
			WorkOrder order456 = repository.GetWorkOrder("456");
			Assert.That(order456.Id, Is.EqualTo(order2.Id));
		}

		[Test]
		public void ShouldSearchBySpecificationWithCreator()
		{
			TestHelper.ClearTables();

			Employee creator1 = new Employee("1", "1", "1", "1");
			Employee creator2 = new Employee("2", "2", "2", "2");
			WorkOrder order1 = new WorkOrder();
			order1.Creator = creator1;
			order1.CreatedDate = new DateTime(1999, 1, 1);
			order1.Number = "123";
			WorkOrder order2 = new WorkOrder();
			order2.Creator = creator2;
			order2.CreatedDate = new DateTime(1999, 1, 1);
			order2.Number = "456";

			ISession session = getSession();
			session.SaveOrUpdate(creator1);
			session.SaveOrUpdate(creator2);
			session.SaveOrUpdate(order1);
			session.SaveOrUpdate(order2);
			session.Flush();
			session.Dispose();

			IWorkOrderRepository repository = new WorkOrderRepository();
			WorkOrderSearchSpecification specification = new WorkOrderSearchSpecification();
			specification.MatchCreator(creator1);
			WorkOrder[] orders = repository.GetWorkOrders(specification);

			Assert.That(orders.Length, Is.EqualTo(1));
			Assert.That(orders[0].Id, Is.EqualTo(order1.Id));
		}

		[Test]
		public void ShouldSearchBySpecificationWithAssignee()
		{
			TestHelper.ClearTables();

			Employee employee1 = new Employee("1", "1", "1", "1");
			Employee employee2 = new Employee("2", "2", "2", "2");
			WorkOrder order1 = new WorkOrder();
			order1.Creator = employee2;
			order1.Assignee = employee1;
			order1.CreatedDate = new DateTime(1999, 1, 1);
			order1.Number = "123";
			WorkOrder order2 = new WorkOrder();
			order2.Creator = employee1;
			order2.Assignee = employee2;
			order2.CreatedDate = new DateTime(1999, 1, 1);
			order2.Number = "456";

			ISession session = getSession();
			session.SaveOrUpdate(employee1);
			session.SaveOrUpdate(employee2);
			session.SaveOrUpdate(order1);
			session.SaveOrUpdate(order2);
			session.Flush();
			session.Dispose();

			IWorkOrderRepository repository = new WorkOrderRepository();
			WorkOrderSearchSpecification specification = new WorkOrderSearchSpecification();
			specification.MatchAssignee(employee1);
			WorkOrder[] orders = repository.GetWorkOrders(specification);

			Assert.That(orders.Length, Is.EqualTo(1));
			Assert.That(orders[0].Id, Is.EqualTo(order1.Id));
		}

		[Test]
		public void ShouldSearchBySpecificationWithStatus()
		{
			TestHelper.ClearTables();

			Employee employee1 = new Employee("1", "1", "1", "1");
			Employee employee2 = new Employee("2", "2", "2", "2");
			WorkOrder order1 = new WorkOrder();
			order1.Creator = employee2;
			order1.Assignee = employee1;
			order1.CreatedDate = new DateTime(1999, 1, 1);
			order1.Number = "123";
			order1.Status = WorkOrderStatus.Assigned;
			WorkOrder order2 = new WorkOrder();
			order2.Creator = employee1;
			order2.Assignee = employee2;
			order2.CreatedDate = new DateTime(1999, 1, 1);
			order2.Number = "456";
			order2.Status = WorkOrderStatus.Draft;

			ISession session = getSession();
			session.SaveOrUpdate(employee1);
			session.SaveOrUpdate(employee2);
			session.SaveOrUpdate(order1);
			session.SaveOrUpdate(order2);
			session.Flush();
			session.Dispose();

			IWorkOrderRepository repository = new WorkOrderRepository();
			WorkOrderSearchSpecification specification = new WorkOrderSearchSpecification();
			specification.MatchStatus(WorkOrderStatus.Assigned);
			WorkOrder[] orders = repository.GetWorkOrders(specification);

			Assert.That(orders.Length, Is.EqualTo(1));
			Assert.That(orders[0].Id, Is.EqualTo(order1.Id));
		}

		[Test]
		public void ShouldSearchBySpecificationWithFullSpecification()
		{
			TestHelper.ClearTables();

			Employee employee1 = new Employee("1", "1", "1", "1");
			Employee employee2 = new Employee("2", "2", "2", "2");
			WorkOrder order1 = new WorkOrder();
			order1.Creator = employee2;
			order1.Assignee = employee1;
			order1.CreatedDate = new DateTime(1999, 1, 1);
			order1.Number = "123";
			order1.Status = WorkOrderStatus.Assigned;
			WorkOrder order2 = new WorkOrder();
			order2.Creator = employee1;
			order2.Assignee = employee2;
			order2.CreatedDate = new DateTime(1999, 1, 1);
			order2.Number = "456";
			order2.Status = WorkOrderStatus.Draft;

			ISession session = getSession();
			session.SaveOrUpdate(employee1);
			session.SaveOrUpdate(employee2);
			session.SaveOrUpdate(order1);
			session.SaveOrUpdate(order2);
			session.Flush();
			session.Dispose();

			IWorkOrderRepository repository = new WorkOrderRepository();
			WorkOrderSearchSpecification specification = new WorkOrderSearchSpecification();
			specification.MatchStatus(WorkOrderStatus.Assigned);
			specification.MatchCreator(employee2);
			specification.MatchAssignee(employee1);
			WorkOrder[] orders = repository.GetWorkOrders(specification);

			Assert.That(orders.Length, Is.EqualTo(1));
			Assert.That(orders[0].Id, Is.EqualTo(order1.Id));
		}
	}
}